home *** CD-ROM | disk | FTP | other *** search
/ AOL File Library: 2,801 to 2,900 / aol-file-protocol-4400-2801-to-2900.zip / AOLDLs / C++ Files Library / CWASTE C++ text editing routi / CWASTE folder.sit / CWASTE folder / TSMSupport.c < prev    next >
Text File  |  1994-07-20  |  13KB  |  558 lines

  1. // { WASTE PROJECT: }
  2. // { Text Services Manager support }
  3.  
  4. // { Copyright ⌐ 1993-1994 Marco Piovanelli }
  5. // { All Rights Reserved }
  6. // C conversion by Dan Crevier
  7.  
  8. #include "WASTEIntf.h"
  9. #include "LongCoords.h"
  10.  
  11. OSErr _WEHiliteRangeArray(TextRangeArrayHandle hTray, WEHandle hWE)
  12. {
  13.     WEPtr pWE;
  14.     TextRangePtr pRange;
  15.     long rangeStart, rangeEnd;
  16.     short hiliteStyle;
  17.     WETextStyle ts;
  18.     short rangeIndex;
  19.     Boolean saveTrayLock;
  20.     OSErr err;
  21.  
  22.     pWE = *hWE;
  23.  
  24.     //{ lock down the range array }
  25.     saveTrayLock = _WESetHandleLock((Handle)hTray, true);
  26.     rangeIndex = (**hTray).fNumOfRanges - 1;
  27.     pRange = (*hTray)->fRange;
  28.  
  29.     //{ walk the hilite range array }
  30.     while (rangeIndex >= 0)
  31.     {
  32.  
  33.         //{ the offsets in the range array are relative to the beginning }
  34.         //{ of the active input area: convert them to absolute offsets }
  35.         rangeStart = pWE->tsmAreaStart + pRange->fStart;
  36.         rangeEnd = pWE->tsmAreaStart + pRange->fEnd;
  37.         hiliteStyle = pRange->fHiliteStyle;
  38.  
  39.         //{ take the absolute value of hiliteStyle }
  40.         hiliteStyle = ABS(hiliteStyle);
  41.  
  42.         //{ if hiliteStyle is kCaretPosition, set the selection range }
  43.         if (hiliteStyle == kCaretPosition)
  44.         {
  45.             pWE->selStart = rangeStart;
  46.             pWE->selEnd = rangeEnd;
  47.         }
  48.         else
  49.         {
  50.             hiliteStyle = hiliteStyle - kRawText;
  51.         }
  52.         //{ otherwise set the WETextStyle flags of the specified range appropriately }
  53.         if ((hiliteStyle >= 0) && (hiliteStyle <= 3))
  54.         {
  55.             ts.tsFlags = 0x10 + BSL(hiliteStyle, tsTSMSelected);
  56.             err = _WESetStyleRange(rangeStart, rangeEnd, weDoFlags, &ts, hWE);
  57.             if (err != noErr)
  58.             {
  59.                 goto cleanup;
  60.             }
  61.         }
  62.         
  63.         //{ go to next text range element }
  64.         rangeIndex = rangeIndex - 1;
  65.         pRange++;
  66.     }
  67.  
  68.     // { clear result code }
  69.     err = noErr;
  70.  
  71. cleanup:
  72.     //{ unlock the range array }
  73.     _WESetHandleLock((Handle)hTray, saveTrayLock);
  74.  
  75.     return err;
  76. }
  77.  
  78. pascal OSErr _WEHandleUpdateActiveInputArea(AppleEvent *ae, AppleEvent *reply,
  79.         long handlerRefCon)
  80. {
  81.     WEHandle hWE;
  82.     WEPtr pWE;
  83.     AEDesc text;
  84.     AEDesc hiliteTray;
  85.     TextRange pinRange;
  86.     long totalLength;
  87.     long fixLength;
  88.     long tsmOffset;
  89.     DescType returnedType;
  90.     long actualSize;
  91.     GrafPtr savePort;
  92.     Boolean saveAutoScroll;
  93.     Boolean saveTextLock;
  94.     Boolean saveWELock;
  95.     OSErr err;
  96.  
  97.     hWE = nil;
  98.  
  99.     //{ initialize descriptors to null values }
  100.     text.descriptorType = typeNull;
  101.     text.dataHandle = nil;
  102.     hiliteTray.descriptorType = typeNull;
  103.     hiliteTray.dataHandle = nil;
  104.  
  105.     //{ extract WE handle }
  106.     err = AEGetParamPtr(ae, keyAETSMDocumentRefcon, typeLongInteger, &returnedType,
  107.         (Ptr)&hWE, sizeof(hWE), &actualSize);
  108.     if (err != noErr)
  109.     {
  110.         goto cleanup;
  111.     }
  112.  
  113.     //{ lock the WE handle }
  114.     saveWELock = _WESetHandleLock((Handle)hWE, true);
  115.     pWE = *hWE;
  116.  
  117.     //{ call the pre-update callback, if present }
  118.     if ((WETSMPreUpdateProcPtr)pWE->tsmPreUpdate != nil)
  119.     {
  120.         ((WETSMPreUpdateProcPtr)pWE->tsmPreUpdate)(hWE);
  121.     }
  122.     
  123.     //{ hide the caret if it's showing }
  124.     if (BTST(pWE->flags, weFCaretVisible))
  125.     {
  126.         _WEDrawCaret(hWE);
  127.     }
  128.     
  129.     //{ extract the text descriptor }
  130.     err = AEGetParamDesc(ae, keyAETheData, typeChar, &text);
  131.     if (err != noErr)
  132.     {
  133.         goto cleanup;
  134.     }
  135.     
  136.     //{ get total length of text in the active input area }
  137.     totalLength = GetHandleSize(text.dataHandle);
  138.  
  139.     //{ extract the length of confirmed text in the active input area }
  140.     err = AEGetParamPtr(ae, keyAEFixLength, typeLongInteger, &returnedType,
  141.         &fixLength, sizeof(fixLength), &actualSize);
  142.     if (err != noErr)
  143.     {
  144.         goto cleanup;
  145.     }
  146.     //{ if fixLength = -1, all text is confirmed }
  147.     if (fixLength == -1)
  148.     {
  149.         totalLength = fixLength;
  150.     }
  151.     //{ if there's currently no active input area, open one }
  152.     if (pWE->tsmAreaStart == kInvalidOffset)
  153.     {
  154.         pWE->tsmAreaStart = pWE->selStart;
  155.         pWE->tsmAreaEnd = pWE->selEnd;
  156.     }
  157.  
  158.     tsmOffset = pWE->tsmAreaStart;
  159.  
  160.     //{ the new text replaces whatever is in the active input area }
  161.     err = _WEDeleteRange(tsmOffset, pWE->tsmAreaEnd, hWE);
  162.     if (err != noErr)
  163.     {
  164.         goto cleanup;
  165.     }
  166.  
  167.     //{ synchronize the null style, so font script matches the keyboard script }
  168.     _WESynchNullStyle(hWE);
  169.  
  170.     //{ set the port font for good measure }
  171.     GetPort(&savePort);
  172.     SetPort(pWE->port);
  173.     TextFont(pWE->nullStyle.runStyle.tsFont);
  174.     SetPort(savePort);
  175.  
  176.     //{ temporarily lock the text }
  177.     saveTextLock = _WESetHandleLock(text.dataHandle, true);
  178.  
  179.     // { insert the text }
  180.     err = _WEInsertText(tsmOffset, *(text.dataHandle), totalLength, hWE);
  181.     if (err != noErr)
  182.     {
  183.         goto cleanup;
  184.     }
  185.     //{ unlock the text }
  186.     _WESetHandleLock(text.dataHandle, saveTextLock);
  187.  
  188.     //{ extract pin range }
  189.     err = AEGetParamPtr(ae, keyAEPinRange, typeTextRange, &returnedType, &pinRange,
  190.         sizeof(pinRange), &actualSize);
  191.     if (err == noErr)
  192.     {
  193.         //{ we want absolute offsets }
  194.         pinRange.fStart = pinRange.fStart + tsmOffset;
  195.         pinRange.fEnd = pinRange.fEnd + tsmOffset;
  196.     }
  197.     else
  198.     {
  199.         //{ a missing pin range descriptor isn't an error; everything else is }
  200.         if (err != errAEDescNotFound)
  201.         {
  202.             goto cleanup;
  203.         }
  204.         //{ default pin range is active input area }
  205.         pinRange.fStart = tsmOffset;
  206.         pinRange.fEnd = pWE->tsmAreaEnd;
  207.     }
  208.  
  209.     //{ extract the highlight range array }
  210.     err = AEGetParamDesc(ae, keyAEHiliteRange, typeTextRangeArray, &hiliteTray);
  211.     if (err != noErr)
  212.     {
  213.         if (err != errAEDescNotFound)
  214.         {
  215.             goto cleanup;
  216.         }
  217.     }
  218.     if (hiliteTray.dataHandle != nil)
  219.     {
  220.         err = _WEHiliteRangeArray((TextRangeArrayHandle)hiliteTray.dataHandle, hWE);
  221.         if (err != noErr)
  222.         {
  223.             goto cleanup;
  224.         }
  225.     }
  226.     else
  227.     {
  228.         pWE->selStart = tsmOffset + fixLength;
  229.         pWE->selEnd = pWE->selStart;
  230.     }
  231.  
  232.     //{ temporarily disable auto-scroll, as we need to scroll manually according to pinRange }
  233.     saveAutoScroll = BTST(pWE->flags, weFAutoScroll);
  234.     BCLR(pWE->flags, weFAutoScroll);
  235.     
  236.     //{ redraw the active input area }
  237.     err = _WERedraw(tsmOffset, tsmOffset + totalLength, hWE);
  238.     if (err != noErr)
  239.     {
  240.         goto cleanup;
  241.     }
  242.  
  243.     if (saveAutoScroll)
  244.     {
  245.     
  246.         //{ re-enable auto-scroll }
  247.         BSET(pWE->flags, weFAutoScroll);
  248.  
  249.         //{ scroll the pin range into view }
  250.         if (_WEScrollIntoView(pinRange.fStart, hWE) == false)
  251.         {
  252.             if (pinRange.fStart != pinRange.fEnd)
  253.             {
  254.                 _WEScrollIntoView(pinRange.fEnd, hWE);
  255.             }
  256.         }
  257.     }
  258.  
  259.     //{ update the boundaries of the active input area }
  260.     //{ if fixLength = totalLength, the inline input session is over: close the active input area }
  261.     if (fixLength == totalLength)
  262.     {
  263.         pWE->tsmAreaStart = kInvalidOffset;
  264.         pWE->tsmAreaEnd = kInvalidOffset;
  265.     }
  266.     else
  267.     {
  268.         //{ otherwise, fixLength defines the boundaries of the active input area }
  269.         pWE->tsmAreaStart = tsmOffset + fixLength;
  270.         pWE->tsmAreaEnd = tsmOffset + totalLength;
  271.     }
  272.  
  273.     //{ call the post-update callback, if present }
  274.     if (pWE->tsmPostUpdate != nil)
  275.     {
  276.         ((WETSMPostUpdateProcPtr)pWE->tsmPostUpdate)(hWE, fixLength, pWE->tsmAreaStart, pWE->tsmAreaEnd,
  277.             pinRange.fStart, pinRange.fEnd);
  278.     }
  279.     //{ clear result code }
  280.     err = noErr;
  281.  
  282. cleanup:
  283.     //{ clean up }
  284.     AEDisposeDesc(&text);
  285.     AEDisposeDesc(&hiliteTray);
  286.  
  287.     //{ unlock the WE record }
  288.     if (hWE !=NULL)
  289.     {
  290.         _WESetHandleLock((Handle)hWE, saveWELock);
  291.     }
  292.  
  293.     //{ return result code }
  294.     return err;
  295. }
  296.  
  297.  
  298. pascal OSErr _WEHandlePositionToOffset (AppleEvent *ae, AppleEvent *reply,
  299.         long handlerRefCon)
  300. {
  301.     WEHandle hWE;
  302.     WEPtr pWE;
  303.     Point position;
  304.     LongPt thePoint;
  305.     short regionClass;
  306.     long offset;
  307.     DescType returnedType;
  308.     long actualSize;
  309.     GrafPtr savePort;
  310.     char edge;
  311.     Boolean saveWELock;
  312.     OSErr err;
  313.  
  314.     hWE = nil;
  315.  
  316.     //{ extract WE handle }
  317.     err = AEGetParamPtr(ae, keyAETSMDocumentRefcon, typeLongInteger, &returnedType,
  318.         &hWE, sizeof(hWE), &actualSize);
  319.     if (err != noErr)
  320.     {
  321.         goto cleanup;
  322.     }
  323.  
  324.     //{ lock the WE record }
  325.     saveWELock = _WESetHandleLock((Handle)hWE, true);
  326.     pWE = *hWE;
  327.  
  328.     // { extract position parameter }
  329.     err = AEGetParamPtr(ae, keyAECurrentPoint, typeQDPoint, &returnedType, &position,
  330.         sizeof(position), &actualSize);
  331.     if (err != noErr)
  332.     {
  333.             goto cleanup;
  334.     }
  335.     //{ convert position to local... }
  336.     GetPort(&savePort);
  337.     SetPort(pWE->port);
  338.     GlobalToLocal(&position);
  339.     SetPort(savePort);
  340.  
  341.     //{ ...and long coordinates }
  342.     WEPointToLongPoint(position, &thePoint);
  343.  
  344.     //{ find the byte offset and the edge value corresponding to the given position }
  345.     offset = WEGetOffset(&thePoint, &edge, hWE);
  346.  
  347.     // { add offset parameter to reply }
  348.     err = AEPutParamPtr(reply, keyAEOffset, typeLongInteger, &offset, sizeof(offset));
  349.     if (err != noErr) 
  350.     {
  351.         goto cleanup;
  352.     }
  353.     
  354.     //{ add edge parameter to reply }
  355.     err = AEPutParamPtr(reply, keyAELeftSide, typeBoolean, &edge, sizeof(edge));
  356.     if (err != noErr)
  357.     {
  358.         goto cleanup;
  359.     }
  360.     //{ determine the region class }
  361.     if (WELongPointInLongRect(&thePoint, &pWE->viewRect))
  362.     {
  363.         if (_WEOffsetInRange(offset, edge, pWE->tsmAreaStart, pWE->tsmAreaEnd))
  364.         {
  365.             regionClass = kTSMInsideOfActiveInputArea;
  366.         }
  367.         else
  368.         {
  369.                 regionClass = kTSMInsideOfBody;
  370.         }
  371.     }
  372.     else
  373.     {
  374.         regionClass = kTSMOutsideOfBody;
  375.     }
  376.     
  377.     //{ add region class parameter to reply }
  378.     err = AEPutParamPtr(reply, keyAERegionClass, typeShortInteger, ®ionClass,
  379.         sizeof(regionClass));
  380.     if (err != noErr)
  381.     {
  382.         goto cleanup;
  383.     }
  384.     
  385.     //{ clear result code }
  386.     err = noErr;
  387.  
  388. cleanup:
  389.     //{ unlock the WE record }
  390.     if (hWE != nil)
  391.     {
  392.         _WESetHandleLock((Handle)hWE, saveWELock);
  393.     }
  394.     
  395.     //{ return result code }
  396.     return err;
  397. }
  398.  
  399. pascal OSErr _WEHandleOffsetToPosition(AppleEvent *ae, AppleEvent *reply, long handlerRefCon)
  400. {
  401.     WEHandle hWE;
  402.     WEPtr pWE;
  403.     long offset;
  404.     LongPt thePoint;
  405.     Point position;
  406.     short lineHeight;
  407.     DescType returnedType;
  408.     long actualSize;
  409.     GrafPtr savePort;
  410.     Boolean saveWELock;
  411.     OSErr err;
  412.  
  413.     hWE = nil;
  414.  
  415.     //{ extract WE handle }
  416.     err = AEGetParamPtr(ae, keyAETSMDocumentRefcon, typeLongInteger, &returnedType, &hWE,
  417.         sizeof(hWE), &actualSize);
  418.     if (err != noErr)
  419.     {
  420.         goto cleanup;
  421.     }
  422.  
  423.     //{ lock the WE record }
  424.     saveWELock = _WESetHandleLock((Handle)hWE, true);
  425.     pWE = *hWE;
  426.  
  427.     //{ if there's no active input area, return errOffsetInvalid }
  428.     if (pWE->tsmAreaStart < 0)
  429.     {
  430.         err = errOffsetInvalid;
  431.         goto cleanup;
  432.     }
  433.     
  434.     //{ extract the offset parameter }
  435.     err = AEGetParamPtr(ae, keyAEOffset, typeLongInteger, &returnedType, &offset, 
  436.         sizeof(offset), &actualSize);
  437.     if (err != noErr)
  438.     {
  439.         goto cleanup;
  440.     }
  441.  
  442.     //{ offset is relative to the beginning of the active input area; we want an absolute offset }
  443.     offset = offset + pWE->tsmAreaStart;
  444.  
  445.     // { make sure the offset is within the input area }
  446.     if ((offset < pWE->tsmAreaStart) || (offset >= pWE->tsmAreaEnd))
  447.     {
  448.         err = errOffsetInvalid;
  449.         goto cleanup;
  450.     }
  451.  
  452.     //{ find the position corresponding to the given offset (in long coordinates) }
  453.     WEGetPoint(offset, &thePoint, &lineHeight, hWE);
  454.     thePoint.v = thePoint.v + lineHeight;
  455.  
  456.     //{ make sure offset is within view rectangle }
  457.     if (!WELongPointInLongRect(&thePoint, &pWE->viewRect))
  458.     {
  459.         err = errOffsetIsOutsideOfView;
  460.         goto cleanup;
  461.     }
  462.  
  463.     //{ convert the point to short... }
  464.     WELongPointToPoint(&thePoint, &position);
  465.  
  466.     //{ ...and global coordinates }
  467.     GetPort(&savePort);
  468.     SetPort(pWE->port);
  469.     LocalToGlobal(&position);
  470.     SetPort(savePort);
  471.  
  472.     //{ add keyAEPoint parameter to the reply Apple event }
  473.     err = AEPutParamPtr(reply, keyAEPoint, typeQDPoint, &position, sizeof(position));
  474.     if (err != noErr)
  475.     {
  476.         goto cleanup;
  477.     }
  478.  
  479.     //{ add keyAETextFont parameter to the reply Apple event }
  480.     err = AEPutParamPtr(reply, keyAETextFont, typeShortInteger, &pWE->nullStyle.runStyle.tsFont,
  481.         sizeof(pWE->nullStyle.runStyle.tsFont));
  482.     if (err != noErr)
  483.     {
  484.         goto cleanup;
  485.     }
  486.     
  487.     //{ add keyAETextPointSize parameter to the reply Apple event }
  488.     err = AEPutParamPtr(reply, keyAETextPointSize, typeShortInteger, 
  489.         &pWE->nullStyle.runStyle.tsSize, sizeof(pWE->nullStyle.runStyle.tsSize));
  490.     if (err != noErr)
  491.     {
  492.         goto cleanup;
  493.     }
  494.  
  495.     //{ add keyAETextLineAscent parameter to the reply Apple event }
  496.     err = AEPutParamPtr(reply, keyAETextLineAscent, typeShortInteger, 
  497.         &pWE->nullStyle.runAscent, sizeof(pWE->nullStyle.runAscent));
  498.     if (err != noErr)
  499.     {
  500.         goto cleanup;
  501.     }
  502.     
  503.     //{ add keyAETextLineHeight parameter to the reply Apple event }
  504.     err = AEPutParamPtr(reply, keyAETextLineHeight, typeShortInteger, 
  505.         &pWE->nullStyle.runHeight, sizeof(pWE->nullStyle.runHeight));
  506.     if (err != noErr)
  507.     {
  508.         goto cleanup;
  509.     }
  510.     
  511.     //{ clear result code }
  512.     err = noErr;
  513.  
  514. cleanup:
  515.     //{ unlock the WE record }
  516.     if (hWE != nil)
  517.     {
  518.         _WESetHandleLock((Handle) hWE, saveWELock);
  519.     }
  520.     
  521.     //{ return result code }
  522.     return err;
  523. }
  524.  
  525. pascal OSErr WEInstallTSMHandlers(void)
  526. {
  527.     OSErr err;
  528.     
  529.     //{ install Apple Event handlers to be used by Text Service components }
  530.     err = AEInstallEventHandler(kTextServiceClass, kUpdateActiveInputArea,
  531.         NewAEEventHandlerProc(_WEHandleUpdateActiveInputArea), 0, false);
  532.     if (err != noErr)
  533.     {
  534.         goto cleanup;
  535.     }
  536.         
  537.     err = AEInstallEventHandler(kTextServiceClass, kPos2Offset, 
  538.         NewAEEventHandlerProc(_WEHandlePositionToOffset), 0, false);
  539.     if (err != noErr)
  540.     {
  541.         goto cleanup;
  542.     }
  543.     
  544.     err = AEInstallEventHandler(kTextServiceClass, kOffset2Pos, 
  545.         NewAEEventHandlerProc(_WEHandleOffsetToPosition), 0, false);
  546.     if (err != noErr)
  547.     {
  548.         goto cleanup;
  549.     }
  550.     
  551.     // { clear result code }
  552.     err = noErr;
  553.  
  554. cleanup:
  555.     // { return result code }
  556.     return err;
  557. }
  558.